/**
  @file
  @author Stefan Frings
*/

#pragma once

#include "qtwebappglobal.h"

#include <QFile>
#include <QTextCodec>

namespace qtwebapp {

/**
 Enhanced version of QString for template processing. Templates
 are usually loaded from files, but may also be loaded from
 prepared Strings.
 Example template file:
 <p><code><pre>
 Hello {username}, how are you?
 
 {if locked}
	 Your account is locked.
 {else locked}
	 Welcome on our system.
 {end locked}
 
 The following users are on-line:
	 Username       Time
 {loop user}
	 {user.name}    {user.time}
 {end user}
 </pre></code></p>
 <p>
 Example code to fill this template:
 <p><code><pre>
 Template t(QFile("test.tpl"),QTextCode::codecForName("UTF-8"));
 t.setVariable("username", "Stefan");
 t.setCondition("locked",false);
 t.loop("user",2);
 t.setVariable("user0.name,"Markus");
 t.setVariable("user0.time,"8:30");
 t.setVariable("user1.name,"Roland");
 t.setVariable("user1.time,"8:45");
 </pre></code></p>
 <p>
 The code example above shows how variable within loops are numbered.
 Counting starts with 0. Loops can be nested, for example:
 <p><code><pre>
 &lt;table&gt;
 {loop row}
	 &lt;tr&gt;
	 {loop row.column}
		 &lt;td&gt;{row.column.value}&lt;/td&gt;
	 {end row.column}
	 &lt;/tr&gt;
 {end row}
 &lt;/table&gt;
 </pre></code></p>
 <p>
 Example code to fill this nested loop with 3 rows and 4 columns:
 <p><code><pre>
 t.loop("row",3);
 
 t.loop("row0.column",4);
 t.setVariable("row0.column0.value","a");
 t.setVariable("row0.column1.value","b");
 t.setVariable("row0.column2.value","c");
 t.setVariable("row0.column3.value","d");
 
 t.loop("row1.column",4);
 t.setVariable("row1.column0.value","e");
 t.setVariable("row1.column1.value","f");
 t.setVariable("row1.column2.value","g");
 t.setVariable("row1.column3.value","h");
 
 t.loop("row2.column",4);
 t.setVariable("row2.column0.value","i");
 t.setVariable("row2.column1.value","j");
 t.setVariable("row2.column2.value","k");
 t.setVariable("row2.column3.value","l");
 </pre></code></p>
 @see TemplateLoader
 @see TemplateCache
*/

class QTWEBAPP_EXPORT Template : public QString {
public:
	
	/**
	  Constructor that reads the template from a string.
	  @param source The template source text
	  @param sourceName Name of the source file, used for logging
	*/
	Template(QString source, QString sourceName);
	
	/**
	  Constructor that reads the template from a file. Note that this class does not
	  cache template files by itself, so using this constructor is only recommended
	  to be used on local filesystem.
	  @param file File that provides the source text
	  @param textCodec Encoding of the source
	  @see TemplateLoader
	  @see TemplateCache
	*/
	Template(QFile& file, QTextCodec* textCodec);
	
	/**
	  Replace a variable by the given value.
	  Affects tags with the syntax
	  
	  - {name}
	  
	  After settings the
	  value of a variable, the variable does not exist anymore,
	  it it cannot be changed multiple times.
	  @param name name of the variable
	  @param value new value
	  @return The count of variables that have been processed
	*/
	int setVariable(QString name, QString value);
	
	/**
	  Set a condition. This affects tags with the syntax
	  
	  - {if name}...{end name}
	  - {if name}...{else name}...{end name}
	  - {ifnot name}...{end name}
	  - {ifnot name}...{else name}...{end name}
	  
	 @param name Name of the condition
	 @param value Value of the condition
	 @return The count of conditions that have been processed
	*/
	int setCondition(QString name, bool value);
	
	/**
	 Set number of repetitions of a loop.
	 This affects tags with the syntax
	 
	 - {loop name}...{end name}
	 - {loop name}...{else name}...{end name}
	 
	 @param name Name of the loop
	 @param repetitions The number of repetitions
	 @return The number of loops that have been processed
	*/
	int loop(QString name, int repetitions);
	
	/**
	 Enable warnings for missing tags
	 @param enable Warnings are enabled, if true
	*/
	void enableWarnings(bool enable=true);
	
private:
	
	/** Name of the source file */
	QString sourceName;
	
	/** Enables warnings, if true */
	bool warnings;
};

} // end of namespace
